home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 March
/
EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso
/
earcd
/
comm2
/
alist.lha
/
src
/
alconfig.e
< prev
next >
Wrap
Text File
|
1995-11-08
|
27KB
|
875 lines
/* ALConfig.M */
OPT MODULE
OPT EXPORT
/* Module to load the global config file, parse it, act on it, then load the list config files */
MODULE 'dos/datetime'
MODULE 'dos/dos'
MODULE 'dos/dosasl'
MODULE 'dos/var'
MODULE 'other/allog'
MODULE 'other/aladd'
MODULE 'other/alcmd'
/* Mailing List Entry */
OBJECT config_node
next:PTR TO config_node
name:PTR TO CHAR /* Unique list name (filename - '.list') */
owner:PTR TO CHAR /* Owner's address */
password:PTR TO CHAR /* Password needed to administer list & change config */
subject:PTR TO CHAR /* String to ensure is in the subject line */
flags /* CNF_* */
approved:PTR TO CHAR /* Approved: password */
sdesc:PTR TO CHAR /* One-Line description of list */
ldesc:PTR TO CHAR /* Multi-line description of list */
footer:PTR TO CHAR /* Multi-line footer to tack onto the end of messages */
header:PTR TO CHAR /* Multi-line headers to insert into header group */
file_get_pwd:PTR TO CHAR /* Password required for file gets */
file_put_pwd:PTR TO CHAR /* Password required for file posts */
welcome:PTR TO CHAR /* Multi-line welcome text appended to default welcome message */
decrypt:PTR TO CHAR /* Command to use to decrypt incoming messages */
encrypt:PTR TO CHAR /* Command to use to encrypt outgoing messages */
keep_headers:PTR TO CHAR /* Multi-line list of headers to keep. NIL if 'none' or 'all' */
digest:PTR TO digest /* Digest structure, or NIL for no digest */
archive_period /* AP_* (should be :CHAR, but there's nothing to offset it) */
users:PTR TO CHAR /* Chain of users on the list */
ENDOBJECT
/* Values for archive_period */
ENUM AP_NONE, AP_DAILY, AP_WEEKLY, AP_MONTHLY, AP_YEARLY
/* Flags for the config_node.flags field */
SET CNF_AUTOCMD_FWD, /* Forward 'posted' commands to owner */
CNF_AUTOCMD_USE, /* Process 'posted' commands */
CNF_CMP_DOMAIN, /* Only compare domain name and user name */
CNF_MOD_LIST_SELF, /* ModerateList: self */
CNF_MOD_LIST_OWN, /* ModerateList: owner */
CNF_MOD_POSTS_SELF, /* ModeratePosts: self */
CNF_MOD_POSTS_OWN, /* ModeratePosts: owner */
CNF_MOD_FILES_SELF, /* ModerateFiles: self */
CNF_MOD_FILES_OWN, /* ModerateFiles: owner */
CNF_MOD_FPOST_SELF, /* ModerateFPosts: self */
CNF_MOD_FPOST_OWN, /* ModerateFPosts: owner */
CNF_MOD_INFO_SELF, /* ModerateInfo: self */
CNF_MOD_INFO_OWN, /* ModerateInfo: owner */
CNF_MOD_WHO_SELF, /* ModerateWho: self */
CNF_MOD_WHO_OWN, /* ModerateWho: owner */
CNF_INVISIBLE, /* Don't show on 'INDEX' output */
CNF_ENCRYPT_EACH, /* '$TO' or '$KEY' is part of encrypt command string; call for each member */
CNF_KEEP_RECEIVED, /* Keep all 'Received:' headers */
CNF_KEEP_HEADERS, /* Keep all headers (excluding 'Received:' if CNF_KEEP_RECEIVED is false) */
CNF_REQUIRE_KEY /* Require a key for every user on the list */
/* Structure to add if there is a digest for a list */
/* Note that it must be a known list */
OBJECT digest
name:PTR TO CHAR /* Name of another valid list to use */
header:PTR TO CHAR /* Multi-Line list of headers to add when posting a digest */
footer:PTR TO CHAR /* Multi-Line divider between posts */
iname:PTR TO CHAR /* Name for 'Issue' */
vname:PTR TO CHAR /* Name for 'Volume', or NIL for no volume */
issue:INT /* Starting issue # */
volume:INT /* Starting volume #, if used */
lines:INT /* Number of lines before triggering post */
size:INT /* Number of K before triggering post */
age:INT /* Number of days before triggering post */
i_v:INT /* Number of issues per volume; ignored if vname=NIL */
time:PTR TO datetime /* DateStamp of first post to the current volume/issue */
current_lines:LONG /* Running # of lines in the current issue */
current_size:LONG /* Running size in bytes of the current issue */
ENDOBJECT
/* These are defined in alist.e, but used here too... */
DEF list_dir, files_dir, config, password:PTR TO CHAR, config_list:PTR TO config_node, hostname:PTR TO CHAR
/*
* Load the global config file and act on it, then close 'config'
*/
PROC parse_config()
DEF str:PTR TO CHAR, x
str := String (80)
WHILE (Fgets (config, str, 80))
x := StrLen (str)
IF (str[x-1] = "\n")
str[x-1] := 0
DEC x
ENDIF
SetStr (str, x)
IF (str[0] = "#") OR (str[0] < 33)
/* Ignore it, it's a comment */
ELSEIF (StrCmp (str, 'ListDir', 7))
IF (list_dir)
log_message ('Successive ListDir directives ignored.\n', LOG_WARNING)
ELSE
x := TrimStr (str+8)
IF (x <> 0) THEN list_dir := Lock (x, ACCESS_READ)
IF (list_dir = NIL)
log_message ('Unable to open requested ListDir.\n', LOG_WARNING)
ENDIF
ENDIF
ELSEIF (StrCmp (str, 'FilesDir', 8))
IF (files_dir)
log_message ('Successive FilesDir directives ignored.\n', LOG_WARNING)
ELSE
x := TrimStr (str+9)
IF (x <> 0) THEN files_dir := Lock (x, ACCESS_READ)
IF (files_dir = NIL) THEN log_message ('Unable to open requested FilesDir.\n', LOG_WARNING)
ENDIF
ELSEIF (StrCmp (str, 'Password', 8))
IF (password)
log_message ('Successive Password directives ignored.\n', LOG_WARNING)
ELSE
x := 9
WHILE (str[x] < 33) AND (str[x] <> 0)
INC x
ENDWHILE
IF (str[x] <> 0)
password := String (EstrLen (str) - x)
StrCopy (password, str+x)
ENDIF
ENDIF
ELSE
log_message ('Unknown directive: ', LOG_WARNING)
log_message (str, LOG_WARNING2)
ENDIF
ENDWHILE
DisposeLink (str)
Close (config)
IF (list_dir = NIL)
log_message ('No list directory specified!\n', LOG_ERROR)
RETURN
ENDIF
/* Get our host name, if present */
str := String (256)
x := GetVar ('HOSTNAME', str, 255, GVF_GLOBAL_ONLY OR GVF_LOCAL_ONLY)
IF (x > 0)
hostname := str
ELSE
DisposeLink (str)
ENDIF
/* Now load the list config files... */
get_list_attrs()
ENDPROC
/*
* Here's where we go through the ListDir directory and open all files ending in .list
*/
PROC get_list_attrs()
DEF fd, tmp:PTR TO config_node, old_dir, ap:PTR TO anchorpath, x, str:PTR TO CHAR
old_dir := CurrentDir (list_dir)
config_list := NIL
NEW ap
IF (MatchFirst ('#?.list', ap))
log_message ('No lists to open.\n', LOG_ERROR)
END ap
CurrentDir (old_dir)
RETURN
ENDIF
LOOP
fd := Open (ap.info.filename, MODE_OLDFILE)
IF (fd = NIL)
log_message ('Unable to open list file "', LOG_ERROR)
log_message (ap.info.filename, LOG_ERROR2)
log_message ('".\n', LOG_ERROR2)
ELSE
log_message ('Reading attributes for list "', LOG_INFO)
log_message (ap.info.filename, LOG_INFO2)
log_message ('".\n', LOG_INFO2)
NEW tmp
/* Need this here 'cause parse_list_attrs has to be able to check for a valid digest list */
tmp.next := config_list
tmp.name := String (StrLen (ap.info.filename)-5)
StrCopy (tmp.name, ap.info.filename)
LowerStr (tmp.name)
x := parse_list_attrs (fd, tmp)
IF (x)
str := String (80)
StringF (str, '#\d while reading list file "\s"\n', x, ap.info.filename)
log_message (str, LOG_ERROR)
DisposeLink (str)
END tmp
ELSE
config_list := tmp
ENDIF
Close (fd)
/* Get the .issue overrides */
str := String (EstrLen (tmp.name) + 6)
StrCopy (str, tmp.name)
StrAdd (str, '.issue')
fd := Open (str, MODE_OLDFILE)
IF (fd)
parse_list_attrs (fd, tmp)
Close (fd)
ENDIF
/* Get the user list */
SetStr (str, EstrLen (tmp.name))
StrAdd (str, '.who')
fd := Open (str, MODE_OLDFILE)
IF (fd)
get_who_list (fd, tmp)
Close (fd)
ELSE
log_message ('No who list available.\n', LOG_WARNING)
ENDIF
DisposeLink (str)
IF (check_list_attrs (tmp))
log_message ('List ignored.\n', LOG_ERROR)
config_list := tmp.next
tmp.next := NIL
free_config (tmp)
ENDIF
ENDIF
IF (MatchNext (ap))
END ap
CurrentDir (old_dir)
RETURN
ENDIF
ENDLOOP
/* We won't ever reach here */
ENDPROC
/*
* Parse the List Attributes in a file and place them in the provided struct
*/
PROC parse_list_attrs (fd, tmp:PTR TO config_node)
DEF str:PTR TO CHAR, x, holdover:PTR TO CHAR, tmp2
str := String (256)
holdover := NIL
WHILE (Fgets (fd, str, 256))
IF (IF (holdover) THEN (str[0] = "\a") ELSE FALSE)
/* Add onto the holdover string */
tmp2 := String (EstrLen (holdover) + StrLen (str) - 1)
StringF (tmp2, '\s\s', holdover, str+1)
DisposeLink (holdover)
holdover := tmp2
ELSE
IF (holdover)
set_list_attr (holdover, tmp)
DisposeLink (holdover)
holdover := NIL
ENDIF
SetStr (str, StrLen (str))
IF (StrCmp (str, 'LongDesc:', 9) OR
StrCmp (str, 'DigestHeader:', 13) OR
StrCmp (str, 'DigestFooter:', 13) OR
StrCmp (str, 'Footer:', 7) OR
StrCmp (str, 'Headers:', 8) OR
StrCmp (str, 'Welcome:', 8) OR
StrCmp (str, 'KeepHeaders:', 12))
/* Possible multi-line */
holdover := String (EstrLen (str))
StrCopy (holdover, str)
ELSEIF (str[0] = "#") OR (str[0] < 33) OR (str[0] = "\a")
str[0] := 0 /* Comment */
ELSE
set_list_attr (str, tmp)
ENDIF
ENDIF
ENDWHILE
IF (holdover)
set_list_attr (holdover, tmp)
DisposeLink (holdover)
ENDIF
ENDPROC IoErr()
/*
* Okay, so I pulled a cheezy move here, leveling this three deep...
*
* Sets an individual attribute. Removes the trailing newline on most attrs.
*/
PROC set_list_attr (str:PTR TO CHAR, cfg:PTR TO config_node)
DEF str2:PTR TO CHAR, tmp:PTR TO LONG, str3:PTR TO CHAR, tmp2
IF (StrLen (str) < 10) THEN RETURN
str2 := String (StrLen (str))
StrCopy (str2, str)
tmp := str2
str3 := find_empty (str2)
IF (str3 = NIL) AND (tmp[0] <> "CmpD")
/* Not a setting */
DisposeLink (str2)
RETURN
ENDIF
str3[0] := 0
IF (tmp[0] <> "Foot")
str2 := TrimStr (str3+1)
ELSE
str2 := str3+1
ENDIF
IF (str2[0] = 0)
/* Empty setting */
DisposeLink (tmp)
RETURN
ENDIF
tmp2 := tmp[0]
SELECT tmp2
CASE "Pass"
IF (tmp[1] = "word")
IF (cfg.password) THEN DisposeLink (cfg.password)
cfg.password := String (StrLen (str2)-1)
StrCopy (cfg.password, str2)
ENDIF
CASE "Arch"
IF (tmp[1] = "iveP")
IF (StrCmp (str2, 'none', 4))
cfg.archive_period := AP_NONE
ELSEIF (StrCmp (str2, 'daily', 5))
cfg.archive_period := AP_DAILY
ELSEIF (StrCmp (str2, 'weekly', 6))
cfg.archive_period := AP_WEEKLY
ELSEIF (StrCmp (str2, 'monthly', 7))
cfg.archive_period := AP_MONTHLY
ELSEIF (StrCmp (str2, 'yearly', 6))
cfg.archive_period := AP_YEARLY
ELSE
log_message ('Unknown value for ArchivePeriod.\n', LOG_WARNING)
ENDIF
ENDIF
CASE "Auto"
IF (StrCmp (tmp+4, 'Cmd', 3))
IF (StrCmp (str2, 'fwd', 3))
cfg.flags := cfg.flags OR CNF_AUTOCMD_FWD
ELSEIF (StrCmp (str2, 'use', 3))
cfg.flags := cfg.flags OR CNF_AUTOCMD_USE
ENDIF
ENDIF
CASE "Appr"
IF (tmp[1] = "oveP")
IF (cfg.approved) THEN DisposeLink (cfg.approved)
cfg.approved := String (StrLen (str2)-1)
StrCopy (cfg.approved, str2)
ENDIF
CASE "Shor"
IF (tmp[1] = "tDes")
IF (cfg.sdesc) THEN DisposeLink (cfg.sdesc)
cfg.sdesc := String (StrLen (str2)-1)
StrCopy (cfg.sdesc, str2)
ENDIF
CASE "Long"
IF (tmp[1] = "Desc")
IF (cfg.ldesc) THEN DisposeLink (cfg.ldesc)
cfg.ldesc := String (StrLen (str2))
StrCopy (cfg.ldesc, str2)
ENDIF
CASE "Foot"
IF (StrCmp (tmp+4, 'er', 2))
IF (cfg.footer) THEN DisposeLink (cfg.footer)
cfg.footer := String (StrLen (str2))
StrCopy (cfg.footer, str2)
ENDIF
CASE "Head"
IF (StrCmp (tmp+4, 'er', 2))
IF (cfg.header) THEN DisposeLink (cfg.header)
cfg.header := String (StrLen (str2))
StrCopy (cfg.header, str2)
ENDIF
CASE "CmpD"
IF (tmp[1] = "omai")
cfg.flags := cfg.flags OR CNF_CMP_DOMAIN
ENDIF
CASE "Mode"
IF (tmp[1] = "rate")
IF (tmp[2] = "List")
tmp2 := CNF_MOD_LIST_SELF
ELSEIF (tmp[2] = "Post")
tmp2 := CNF_MOD_POSTS_SELF
ELSEIF (tmp[2] = "File")
tmp2 := CNF_MOD_FILES_SELF
ELSEIF (tmp[2] = "FPos")
tmp2 := CNF_MOD_FPOST_SELF
ELSEIF (tmp[2] = "Info")
tmp2 := CNF_MOD_INFO_SELF
ELSEIF (StrCmp (tmp+8, 'Who', 3))
tmp2 := CNF_MOD_WHO_SELF
ELSE
tmp2 := NIL
ENDIF
IF (tmp2)
IF (StrCmp (str2, 'all', 3))
/* This is the default */
ELSEIF (StrCmp (str2, 'self', 4))
cfg.flags := cfg.flags OR tmp2
ELSEIF (StrCmp (str2, 'owner', 5))
cfg.flags := cfg.flags OR Shl (tmp2, 1)
ELSE
log_message ('Unknown value for Moderate.\n', LOG_WARNING)
ENDIF
ENDIF
ENDIF
CASE "File"
IF (tmp[1] = "GetP")
IF (cfg.file_get_pwd) THEN DisposeLink (cfg.file_get_pwd)
cfg.file_get_pwd := String (StrLen (str2)-1)
StrCopy (cfg.file_get_pwd, str2)
ELSEIF (tmp[1] = "PutP")
IF (cfg.file_put_pwd) THEN DisposeLink (cfg.file_put_pwd)
cfg.file_put_pwd := String (StrLen (str2)-1)
StrCopy (cfg.file_put_pwd, str2)
ENDIF
CASE "Owne"
IF (cfg.owner) THEN DisposeLink (cfg.owner)
cfg.owner := String (StrLen (str2)-1)
StrCopy (cfg.owner, str2)
CASE "Subj"
IF (cfg.subject) THEN DisposeLink (cfg.subject)
cfg.subject := String (StrLen (str2) - 1) /* Drop the \n */
StrCopy (cfg.subject, str2)
CASE "Welc"
IF (cfg.welcome) THEN DisposeLink (cfg.welcome)
cfg.welcome := String (StrLen (str2))
StrCopy (cfg.welcome, str2)
CASE "Visi"
IF (StrCmp (str2, 'yes', 3))
/* Default */
ELSEIF (StrCmp (str2, 'no', 2))
cfg.flags := cfg.flags OR CNF_INVISIBLE
ELSE
log_message ('Unknown value for Visible.\n', LOG_WARNING)
ENDIF
CASE "Decr"
IF (cfg.decrypt) THEN DisposeLink (cfg.decrypt)
cfg.decrypt := String (StrLen (str2)-1)
StrCopy (cfg.decrypt, str2)
CASE "Encr"
IF (cfg.encrypt) THEN DisposeLink (cfg.encrypt)
cfg.encrypt := String (StrLen (str2)-1)
StrCopy (cfg.encrypt, str2)
CASE "Keep"
IF (tmp[1] = "Rece")
IF (StrCmp (str2, 'yes', 3))
cfg.flags := cfg.flags OR CNF_KEEP_RECEIVED
ELSEIF (StrCmp (str2, 'no', 2))
/* Default */
ELSE
log_message ('Unknown value to KeepReceived.\n', LOG_WARNING)
ENDIF
ELSEIF (tmp[1] = "Head")
IF (StrCmp (str2, 'all', 3))
cfg.flags := cfg.flags OR CNF_KEEP_HEADERS
ELSEIF (StrCmp (str2, 'none', 4))
/* Default */
ELSE
/* List of headers */
IF (cfg.keep_headers) THEN DisposeLink (cfg.keep_headers)
cfg.keep_headers := String (StrLen (str2))
StrCopy (cfg.keep_headers, str2)
ENDIF
ENDIF
CASE "Requ"
IF (tmp[1] = "ireK")
IF (StrCmp (str2, 'yes', 3))
cfg.flags := cfg.flags OR CNF_REQUIRE_KEY
ELSEIF (StrCmp (str2, 'no', 2))
/* Default */
ELSE
log_message ('Unknown value for RequireKey.\n', LOG_WARNING)
ENDIF
ENDIF
/* All Digest stuff here */
CASE "Dige"
IF (cfg.digest = NIL) THEN NEW cfg.digest
IF (tmp[1] = "stNa")
IF (cfg.digest.name) THEN DisposeLink (cfg.digest.name)
cfg.digest.name := String (StrLen (str2)-1)
StrCopy (cfg.digest.name, str2)
ELSEIF (tmp[1] = "stIs")
IF (StrCmp (tmp+8, 'sueName', 7))
IF (cfg.digest.iname) THEN DisposeLink (cfg.digest.iname)
cfg.digest.iname := String (StrLen (str2)-1)
StrCopy (cfg.digest.iname, str2)
ELSEIF (StrCmp (tmp+8, 'sue', 3))
cfg.digest.issue := Val (str2)
ENDIF
ELSEIF (tmp[1] = "stHe")
IF (cfg.digest.header) THEN DisposeLink (cfg.digest.header)
cfg.digest.header := String (StrLen (str2))
StrCopy (cfg.digest.header, str2)
ELSEIF (tmp[1] = "stFo")
IF (cfg.digest.footer) THEN DisposeLink (cfg.digest.footer)
cfg.digest.footer := String (StrLen (str2))
StrCopy (cfg.digest.footer, str2)
ELSEIF (tmp[1] = "stSi")
cfg.digest.size := Val (str2)
ELSEIF (tmp[1] = "stLi")
cfg.digest.lines := Val (str2)
ELSEIF (tmp[1] = "stAg")
cfg.digest.age := Val (str2)
ELSEIF (tmp[1] = "stVo")
IF (StrCmp (tmp+8, 'lumeName', 8))
IF (cfg.digest.vname) THEN DisposeLink (cfg.digest.vname)
cfg.digest.vname := String (StrLen (str2)-1)
StrCopy (cfg.digest.vname, str2)
ELSEIF (tmp[2] = "lume")
cfg.digest.volume := Val (str2)
ELSEIF (tmp[2] = "lIss")
cfg.digest.i_v := Val (str2)
ENDIF
/* These should ONLY be found in the .issue files! */
ELSEIF (tmp[1] = "stCu")
IF (tmp[2] = "Line")
cfg.digest.current_lines := Val (str2)
ELSEIF (tmp[2] = "Size")
cfg.digest.current_size := Val (str2)
ELSEIF (tmp[2] = "Date")
IF (cfg.digest.time = NIL)
cfg.digest.time := New (SIZEOF datetime)
ENDIF
IF (tmp[3] = "Days")
cfg.digest.time.stamp.days := Val (str2)
ELSEIF (tmp[3] = "Mins")
cfg.digest.time.stamp.minute := Val (str2)
ELSEIF (tmp[3] = "Tick")
cfg.digest.time.stamp.tick := Val (str2)
ENDIF
ENDIF
ENDIF
DEFAULT
log_message ('Unknown option: ', LOG_WARNING)
log_message (str2, LOG_WARNING2)
ENDSELECT
DisposeLink (tmp)
ENDPROC
/*
* Free up all memory allocated by this file
*/
PROC free_config (cfg=NIL)
DEF tmp:PTR TO config_node
IF (cfg = NIL)
IF (list_dir) THEN UnLock (list_dir)
IF (files_dir) THEN UnLock (files_dir)
IF (password) THEN DisposeLink (password)
cfg := config_list
ENDIF
WHILE (cfg)
tmp := cfg
IF (tmp.name) THEN DisposeLink (tmp.name)
IF (tmp.owner) THEN DisposeLink (tmp.owner)
IF (tmp.password) THEN DisposeLink (tmp.password)
IF (tmp.subject) THEN DisposeLink (tmp.subject)
IF (tmp.approved) THEN DisposeLink (tmp.approved)
IF (tmp.sdesc) THEN DisposeLink (tmp.sdesc)
IF (tmp.ldesc) THEN DisposeLink (tmp.ldesc)
IF (tmp.footer) THEN DisposeLink (tmp.footer)
IF (tmp.header) THEN DisposeLink (tmp.header)
IF (tmp.file_get_pwd) THEN DisposeLink (tmp.file_get_pwd)
IF (tmp.file_put_pwd) THEN DisposeLink (tmp.file_put_pwd)
IF (tmp.welcome) THEN DisposeLink (tmp.welcome)
IF (tmp.decrypt) THEN DisposeLink (tmp.decrypt)
IF (tmp.encrypt) THEN DisposeLink (tmp.encrypt)
IF (tmp.keep_headers) THEN DisposeLink (tmp.keep_headers)
IF (tmp.digest)
IF (tmp.digest.name) THEN DisposeLink (tmp.digest.name)
IF (tmp.digest.header) THEN DisposeLink (tmp.digest.header)
IF (tmp.digest.footer) THEN DisposeLink (tmp.digest.footer)
IF (tmp.digest.iname) THEN DisposeLink (tmp.digest.iname)
IF (tmp.digest.vname) THEN DisposeLink (tmp.digest.vname)
IF (tmp.digest.time) THEN Dispose (tmp.digest.time)
END tmp.digest
ENDIF
tmp := tmp.next
END cfg
cfg := tmp
ENDWHILE
ENDPROC
/*
* Find a list's config entry, or return NIL
*/
PROC find_list (str:PTR TO CHAR)
DEF tmp:PTR TO config_node
IF (str = NIL) THEN RETURN NIL
IF (str[0] = 0) THEN RETURN NIL
tmp := config_list
WHILE (tmp)
IF (StrCmp (str, tmp.name)) THEN RETURN tmp
tmp := tmp.next
ENDWHILE
ENDPROC NIL
/*
* Loads in a who list into a config node.
*/
PROC get_who_list (fd, cfg:PTR TO config_node)
DEF buff:PTR TO CHAR, str:PTR TO CHAR, str2
buff := String (256)
WHILE (Fgets (fd, buff, 256))
str2 := TrimStr (buff)
IF (str2[0])
str := String (StrLen (str2)-1) /* Drop \n */
StrCopy (str, str2)
cfg.users := add_link (cfg.users, str)
ENDIF
ENDWHILE
DisposeLink (buff)
ENDPROC
/*
* Checks validity of a list's configurations, and returns TRUE if something's wrong.
*/
PROC check_list_attrs (cfg:PTR TO config_node)
/* Should check for the digest being a valid list, if present */
IF (cfg.owner = NIL) OR (cfg.password = NIL) THEN RETURN TRUE
ENDPROC FALSE
/*
* Checks if a user is on a given list
*
* who is a List of E Strings
*
* flag should be (list.flags AND CNF_CMP_DOMAIN)
*
* Returns the string entry on the users list if it is found.
*/
PROC on_list (addr:PTR TO CHAR, who:PTR TO CHAR, flag)
DEF s1:PTR TO CHAR, s2:PTR TO CHAR, tmp
s1 := String (80)
s2 := String (80)
StrCopy (s1, addr)
IF (flag)
tmp := InStr (addr, '@')
IF (tmp = -1)
tmp := InStr (addr, '!')
IF (tmp = -1)
/* Localhost */
StringF (s1, '\s@\s', addr, hostname)
ENDIF
ENDIF
ENDIF
IF (flag) THEN domain_only (s1)
WHILE (who)
StrCopy (s2, who)
IF (flag)
tmp := InStr (s2, '@')
IF (tmp = -1)
tmp := InStr (s2, '!')
IF (tmp = -1)
/* Localhost */
StringF (s2, '\s@\s', who, hostname)
ENDIF
ENDIF
ENDIF
IF (StrCmp (s1, s2))
DisposeLink (s1)
DisposeLink (s2)
RETURN who
ENDIF
who := Next (who)
ENDWHILE
DisposeLink (s1)
DisposeLink (s2)
ENDPROC FALSE
/*
* Removes the 'non-domain' portion of an address
*/
PROC domain_only (str:PTR TO CHAR)
DEF s:PTR TO CHAR, x, y, z
s := String (EstrLen (str))
x := InStr (str, '@')
IF (x < 1)
/* Try UUCP name */
x := InStr (str, '!')
IF (x = -1) THEN RETURN /* No host address! */
/* UUCP name */
/* I could be wrong about this formulae, but I have nothing to test it with */
y := x; z := -1
WHILE ((x := InStr (str, '!', y+1)) > -1)
z := y; y := x
ENDWHILE
IF (z > -1) AND (y > z+1)
StrCopy (s, str+z+1)
ELSE
StrCopy (s, str)
ENDIF
ELSE
/* It's a little harder to piece together for normal Internet addresses... */
StrCopy (s, str, x+1) /* Include the @ */
y := x; z := -1
WHILE ((x := InStr (str, '.', y+1)) > -1)
z := y; y := x
ENDWHILE
IF (z > -1) AND (y > z+1)
StrAdd (s, str+z+1)
ELSE
StrAdd (s, y)
ENDIF
ENDIF
StrCopy (str, s)
ENDPROC
/*
* Writes out a list's users to listname.who
*/
PROC write_user_list (list:PTR TO config_node)
DEF s:PTR TO CHAR, fd, s2:PTR TO CHAR, old_dir
old_dir := CurrentDir (list_dir)
s := String (80)
StrCopy (s, list.name)
StrAdd (s, '.who')
fd := Open (s, MODE_NEWFILE)
IF (fd)
/* write who list */
s2 := list.users
WHILE (s2)
Fwrite (fd, s2, 1, EstrLen (s2))
FputC (fd, "\n")
s2 := Next (s2)
ENDWHILE
Close (fd)
ELSE
log_message ('Not able to write who list for "', LOG_WARNING)
log_message (s, LOG_WARNING2)
log_message ('".\n', LOG_WARNING2)
CurrentDir (old_dir)
RETURN FALSE
ENDIF
DisposeLink (s)
CurrentDir (old_dir)
ENDPROC TRUE
/*
* Writes out the current digest issue information.
*/
PROC write_issue (list:PTR TO config_node)
DEF str:PTR TO CHAR, fd, str2:PTR TO CHAR, old_dir
str := String (EstrLen (list.name) + 6)
StringF (str, '\s.issue', list.name)
old_dir := CurrentDir (list_dir)
fd := Open (str, MODE_NEWFILE)
IF (fd = NIL)
log_message ('Unable to write issue information for list "', LOG_ERROR)
log_message (list.name, LOG_ERROR2)
log_message ('".\n', LOG_ERROR2)
DisposeLink (str)
CurrentDir (old_dir)
RETURN
ENDIF
str2 := String (80)
StringF (str2, 'DigestIssue: \d\n', list.digest.issue)
Fputs (fd, str2)
IF (list.digest.volume)
StringF (str2, 'DigestVolume: \d\n', list.digest.volume)
Fputs (fd, str2)
ENDIF
StringF (str2, 'DigestCuLine: \d\n', list.digest.current_lines)
Fputs (fd, str2)
StringF (str2, 'DigestCuSize: \d\n', list.digest.current_size)
Fputs (fd, str2)
IF (list.digest.time)
StringF (str2, 'DigestCuDateDays: \d\n', list.digest.time.stamp.days)
Fputs (fd, str2)
StringF (str2, 'DigestCuDateMins: \d\n', list.digest.time.stamp.minute)
Fputs (fd, str2)
StringF (str2, 'DigestCuDateTick: \d\n', list.digest.time.stamp.tick)
Fputs (fd, str2)
ENDIF
Close (fd)
CurrentDir (old_dir)
DisposeLink (str2)
DisposeLink (str)
ENDPROC
/*
* Low-level loads in a file as a chain of E Strings.
*/
PROC load_in_file (fd)
DEF str:PTR TO CHAR, buff:PTR TO CHAR, head
str := head := NIL
buff := String (256)
WHILE (Fgets (fd, buff, 256))
str := String (StrLen (buff))
StrCopy (str, buff)
head := add_link (head, str)
ENDWHILE
ENDPROC head